package com.mo.axion.service.api.impl.action.send;

import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Throwables;
import com.mo.axion.common.constant.CommonConstant;
import com.mo.axion.common.domain.TaskInfo;
import com.mo.axion.common.dto.model.ContentModel;
import com.mo.axion.common.enums.ChannelType;
import com.mo.axion.common.enums.RespStatusEnum;
import com.mo.axion.common.pipeline.BusinessProcess;
import com.mo.axion.common.pipeline.ProcessContext;
import com.mo.axion.common.vo.BasicResultVO;
import com.mo.axion.domain.MessageParam;
import com.mo.axion.service.api.impl.domain.SendTaskModel;
import com.mo.axion.support.dao.MessageTemplateDao;
import com.mo.axion.support.domain.MessageTemplate;
import com.mo.axion.support.utils.ContentHolderUtil;
import com.mo.axion.support.utils.TaskInfoUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.lang.reflect.Field;
import java.util.*;

/**
 * @author Mo
 * @createTime 2024/2/1 21:02
 * @description 参数组装过程
 */
@Slf4j
@Service
public class SendAssembleAction implements BusinessProcess<SendTaskModel> {

    private static final String LINK_NAME = "url";

    @Autowired
    private MessageTemplateDao messageTemplateDao;


    /**
     * 根据不同类型的模板 对模板中的占位符进行组装替换
     *
     * @param context
     */
    @Override
    public void process(ProcessContext<SendTaskModel> context) {
        SendTaskModel processModel = context.getProcessModel();
        Long messageTemplateId = processModel.getMessageTemplateId();
        try {
            // 查询是否存在该模板
            Optional<MessageTemplate> messageTemplate = messageTemplateDao.findById(messageTemplateId);
            if (!messageTemplate.isPresent() || messageTemplate.get().getIsDeleted().equals(CommonConstant.TRUE)) {
                context.setIsNeedBreak(true).setResponse(BasicResultVO.fail(RespStatusEnum.TEMPLATE_NOT_FOUND));
                return;
            }
            //  把参数组装到模板中
            List<TaskInfo> taskInfoList = assembleTaskInfo(processModel, messageTemplate.get());
            processModel.setTaskInfoList(taskInfoList);
        } catch (Exception e) {
            context.setIsNeedBreak(true).setResponse(BasicResultVO.fail(RespStatusEnum.SERVICE_ERROR));
            log.error("assemble task failed! templateId:{}, e:{}", messageTemplateId, Throwables.getStackTraceAsString(e));
        }
    }

    /**
     * 组装TaskInfo任务消息
     * @param sendTaskModel
     * @param messageTemplate
     * @return
     */
    private List<TaskInfo> assembleTaskInfo(SendTaskModel sendTaskModel, MessageTemplate messageTemplate) {
        //  参数列表
        List<MessageParam> messageParamList = sendTaskModel.getMessageParamList();
        List<TaskInfo> taskInfoList = new ArrayList<>();
        //  组装参数
        for (MessageParam messageParam : messageParamList) {
            TaskInfo taskInfo = TaskInfo.builder()
                    .bizId(messageParam.getBizId())
                    .messageId(TaskInfoUtils.generateMessageId())
                    .messageTemplateId(messageTemplate.getId())
                    .businessId(TaskInfoUtils.generateBusinessId(
                            messageTemplate.getId(), messageTemplate.getTemplateType()
                    ))
                    .receiver(new HashSet<>(Arrays.asList(
                            messageParam.getReceiver()
//                            .split(CommonConstant.COMMA)
                                    .split(String.valueOf(StrUtil.C_COMMA))
                    )))
                    .idType(messageTemplate.getIdType())
                    .sendChannel(messageTemplate.getSendChannel())
                    .templateType(messageTemplate.getTemplateType())
                    .msgType(messageTemplate.getMsgType())
                    .shieldType(messageTemplate.getShieldType())
                    .sendAccount(messageTemplate.getSendAccount())
                    .contentModel(getContentModelValue(messageTemplate, messageParam)).build();
            //  若无bizId使用MessageId为bizId
            if (StrUtil.isBlank(taskInfo.getBizId())) {
                taskInfo.setBizId(taskInfo.getMessageId());
            }
            taskInfoList.add(taskInfo);
        }
        return taskInfoList;
    }

    /**
     * 获取contentModel，替换模板msgContent种占位符信息
     * @param messageTemplate
     * @param messageParam
     * @return
     */
    private static ContentModel getContentModelValue (MessageTemplate messageTemplate, MessageParam messageParam) {
        // 得到真正的ContentModel 类型
        Integer sendChannel = messageTemplate.getSendChannel();
        Class<? extends ContentModel> channelContentModelClass = ChannelType.getChannelModelClassByCode(sendChannel);

        // 得到模板的 msgContent 和 入参
        Map<String, String> variables = messageParam.getVariables();
        JSONObject jsonObject = JSON.parseObject(messageTemplate.getMsgContent());

        //  通过反射组装出 contentModel
        Field[] fields = ReflectUtil.getFields(channelContentModelClass);
        ContentModel contentModel = ReflectUtil.newInstance(channelContentModelClass);
        for (Field field : fields) {
            String originValue = jsonObject.getString(field.getName());

            if (StrUtil.isNotBlank(originValue)) {
                String resultValue = ContentHolderUtil.replacePlaceHolder(originValue, variables);
                Object resultObject = JSONUtil.isJsonObj(resultValue) ? JSONUtil.toBean(resultValue, field.getType()) : resultValue;
                ReflectUtil.setFieldValue(contentModel, field, resultObject);
            }
        }

        //  如果 url 字段处理 TODO
        String url = (String) ReflectUtil.getFieldValue(contentModel, LINK_NAME);
        if (StrUtil.isNotBlank(url)) {
            // TODO
        }
        return contentModel;
    }
}
